package l1j.server.server.model.Instance;

import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.opqlo.Server.L1World.L1World;
import l1j.server.Thread.GeneralThreadPool;
import l1j.server.server.IdFactory;
import l1j.server.server.datatables.MagicDollTable;
import l1j.server.server.datatables.SprTable;
import l1j.server.server.model.L1CastleLocation;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_DollPack;
import l1j.server.server.serverpackets.S_SPMR;
import l1j.server.server.templates.L1Npc;
import l1j.server.server.serverpackets.S_DoActionGFX;
import l1j.server.server.serverpackets.S_OwnCharStatus;//TODO 魔法娃娃DB化
import l1j.server.server.serverpackets.S_RemoveObject;
import l1j.server.server.serverpackets.S_SkillIconGFX;//TODO 魔法娃娃DB化
import l1j.server.server.templates.L1MagicDoll;//TODO 魔法娃娃DB化
import l1j.server.server.utils.Random;
public class L1DollInstance extends L1NpcInstance {
	private static final Logger _log = Logger.getLogger(L1DollInstance.class.getName());
	private static final long serialVersionUID = 1L;
	public static final int DOLL_TIME = 1800000;

	private int _itemId;//TODO 魔法娃娃DB化
	private int _itemObjId, _stayCount;
	private boolean _isDelete = false;//TODO 魔法娃娃DB化
	private boolean _haveAction = true;



	// ターゲットがいない場合の処理
	@Override
	public boolean noTarget() {
		if ((_master != null) && !_master.isDead()
				&& (_master.getMapId() == getMapId())) {
			final int KM = getLocation().getTileLineDistance(_master.getLocation());
			if(KM > 10){
				setSleepTime(calcSleepTime(getPassispeed(), MOVE_SPEED));
				L1World.getInstance().moveVisibleObject(this, getMapId());
				setX(_master.getX());
				setY(_master.getY());
				setMap(_master.getMap());
				setHeading(5);
				_stayCount =0;
			}else if (KM > 2) {
				if (_npcMove != null) {
					_npcMove.setDirectionMove(_npcMove.moveDirection(_master.getX(), _master.getY()));
					setSleepTime(calcSleepTime(getPassispeed(), MOVE_SPEED));
					_stayCount =0;
				}
			} else {
				// 魔法娃娃 - 特殊動作
				_stayCount++;
				if(_haveAction && _stayCount >5){
					dollAction();
				}
			}
		} else {
			_isDelete = true;
			deleteDoll();
			return true;
		}
		return false;
	}
	// 表情動作
	private void dollAction() {
		final int actionCode = this.getAction();
		if(actionCode >0){
			if (Random.nextInt(100) + 1 <= 10) {
				broadcastPacketAll(new S_DoActionGFX(getId(), actionCode));
				setSleepTime(calcSleepTime(SprTable.getInstance().getSprSpeed(getTempCharGfx(),actionCode), 0)); //
				_stayCount =0;
			}
		}else{
			_haveAction = false;
		}
	}
	// 時間計測用
	class DollTimer implements Runnable {
		@Override
		public void run() {
			if (_destroyed) { // 既に破棄されていないかチェック
				return;
			}
			deleteDoll();
		}
	}
	private L1MagicDoll _dollTemp;

	public L1DollInstance( L1Npc template,  L1PcInstance pc,  int itemId,int itemObjId) {//TODO 魔法娃娃DB化
		super(template);
		try {
			_dollTemp = MagicDollTable.getInstance().getTemplate(itemId);
			setId(IdFactory.getInstance().nextId());
			setItemId(itemId);//TODO 魔法娃娃DB化
			setItemObjId(itemObjId);
			GeneralThreadPool.getInstance().schedule(new DollTimer(), DOLL_TIME);
			setMaster(pc);
			int x =pc.getX() + Random.nextInt(5) - 2;
			int y =pc.getY() + Random.nextInt(5) - 2;
			final short mapId = pc.getMapId();
			if(L1CastleLocation.checkInAllfatArea(x, y,mapId)){//opqlo 賭肥區判斷
				x =pc.getX();
				y =pc.getY();
			}
			setX(x);
			setY(y);
			setMap(mapId);
			setHeading(5);
			setLightSize(template.getLightSize());
			setStr(_dollTemp.getStr());
			setDex(_dollTemp.getDex());
			setCon(_dollTemp.getCon());
			setInt(_dollTemp.getInt());
			setWis(_dollTemp.getWis());
			setCha(_dollTemp.getCha());
			setMr(_dollTemp.getMr());
			//doll.getearth()
			addEarth(_dollTemp.getearth());
			addFire(_dollTemp.getfire());
			addWater(_dollTemp.getwater());
			addWind(_dollTemp.getWind());
			setAction(_dollTemp.getActionlist());
			setAc(_dollTemp.getAc());

			L1World.getInstance().storeObject(this);
			L1World.getInstance().addVisibleObject(this);
			for (final L1PcInstance _pc : L1World.getInstance().getRecognizePlayer(this)) {
				onPerceive(_pc);
			}
			pc.getDollList().addDoll(this);
//			pc.addDoll(this);
			if (!isAiRunning()) {
				startAI();
			}
			pc.sendPackets(new S_OwnCharStatus(pc));
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}

	public void deleteDoll() {
		L1PcInstance pc = (L1PcInstance) _master;
		try {
			if (pc != null && _isDelete) {
				pc.sendPackets(new S_SkillIconGFX(56, 0));
			} 
			if (pc != null){
				pc.sendPackets(new S_SPMR(pc));
				pc.sendPackets(new S_OwnCharStatus(pc));
				pc.getDollList().removeDoll(this);
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}
	public void deleteMe() {
		if (this._destroyed) {
			return;
		}

		this._destroyed = true;
		if (this.getInventory() != null) {
			this.getInventory().clearItems();
		}

		this.allTargetClear();
		this._master = null;

		// 是否具有隊伍
		if (this.isReSpawn()) {
			this.onDecay(true);
		}
		// 清空清單
		_hateList.clear();
		_dropHateList.clear();
		_targetItemList.clear();

		L1World.getInstance().removeVisibleObject(this);
		L1World.getInstance().removeObject(this);

		// 畫面內可見範圍物件取回
		final List<L1PcInstance> players = L1World.getInstance().getRecognizePlayer(this);
		if (players.size() > 0) {
			for (final L1PcInstance tgpc : players) {
				if (tgpc != null) {
					tgpc.removeKnownObject(this);
					// 移除顯示
					tgpc.sendPackets(new S_RemoveObject(this));
				}
			}
		}
		// 認識消除
		this.removeAllKnownObjects();
	}

	@Override
	public void onPerceive(final L1PcInstance perceivedFrom) {
		perceivedFrom.addKnownObject(this);
		perceivedFrom.sendPackets(new S_DollPack(this, perceivedFrom));
	}

	@Override
	public void onItemUse() {
		if (!isActived()) {
			// １００％の確率でヘイストポーション使用
			useItem(USEITEM_HASTE, 100);
		}
	}

	@Override
	public void onGetItem(final L1ItemInstance item) {
		if (getNpcTemplate().get_digestitem() > 0) {
			setDigestItem(item);
		}
		if (Arrays.binarySearch(haestPotions, item.getItem().getItemId()) >= 0) {
			useItem(USEITEM_HASTE, 100);
		}
	}

	public int getItemObjId() {
		return _itemObjId;
	}


	public void setItemObjId(final int i) {
		_itemObjId = i;
	}

	//TODO 魔法娃娃DB化
	public int getItemId() {
		return _itemId;
	}

	public void setItemId(final int i) {
		_itemId = i;
		//TODO 魔法娃娃DB化
	}
	private int[] _action;

	private void setAction(final int[] action){
		if(action !=null){
			int size =0;
			for(final int c : action){
				if(c >0){
					size++;
				}
			}
			if(size ==2){
				_action = action;
			}else{
				_action = new int[1];
				_action[0] = action[0];
			}
		}
	}
	private int getAction(){
		if(_action == null){
			return 0;
		}
		if(_action.length >1){
			final int ran = Random.nextInt(100)+1;
			if(ran>50){
				return _action[0];
			}else{
				return _action[1];
			}
		}else{
			return _action[0];
		}
	}

	private int _srcHprTime , _hprTime , _hprValue,
	_srcMprTime , _mprTime , _mprValue;

	public boolean hasHprTime(){
		return _hprValue>0;
	}
	public boolean hasMprTime(){
		return _mprValue>0;
	}

	/**設定娃娃時間性回血**/
	public void setHprTime(final int time , final int value){
		if(value <=0){
			return;
		}
		_hprValue = value;
		_srcHprTime = time;
		_hprTime = time;
	}

	/**設定娃娃時間性回魔**/
	public void setMprTime(final int time , final int value){
		if(value <=0){
			return;
		}
		_mprValue = value;
		_srcMprTime = time;
		_mprTime = time;
	}


	/**取得娃娃時間性回血**/
	public int getHprForTime(){
		if(_hprValue >0){
			_hprTime--;
			if(_hprTime <=0){
				_hprTime = _srcHprTime;
				return _hprValue;
			}
		}
		return 0;
	}
	/**取得娃娃時間性回魔**/
	public int getMprForTime(){
		if(_mprValue >0){
			_mprTime--;
			if(_mprTime <=0){
				_mprTime = _srcMprTime;
				return _mprValue;
			}
		}
		return 0;
	}
}
